package com.zju.DoctorGo.service.impl;

import com.zju.DoctorGo.config.AlipayConfig;
import com.zju.DoctorGo.mapper.BillMapper;
import com.zju.DoctorGo.entity.Bill;
import com.zju.DoctorGo.entity.PaymentStatusEnum;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.java_websocket.exceptions.InvalidDataException;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zju.DoctorGo.dto.BillDTO;
import com.zju.DoctorGo.dto.PaymentRequestDTO;
import com.zju.DoctorGo.entity.Bill;
import com.zju.DoctorGo.mapper.BillMapper;
import com.zju.DoctorGo.service.PaymentService;

import java.io.UnsupportedEncodingException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Arrays;
import java.util.Collections;

import org.apache.ibatis.exceptions.PersistenceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.apache.ibatis.exceptions.PersistenceException;
import java.sql.SQLIntegrityConstraintViolationException;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class PaymentServiceImpl extends ServiceImpl<BillMapper, Bill> implements PaymentService {
    @Autowired
    private BillMapper billMapper;

    public void createBill(BillDTO billDto) throws Exception {
        billMapper.insertBill(new Bill(billDto));
    }  

    public void updateBillStatByID(String billId, PaymentStatusEnum stat) throws Exception{
        billMapper.updatePaymentStatus(billId, stat);
    }

    public int deleteBillById(String billId) throws Exception {
        return billMapper.deleteBillById(billId);
    }

    public Bill getBillById(String billId) throws Exception{
        return billMapper.selectBillById(billId);
    }

    @Transactional(readOnly = true)
    public List<Bill> selectBillsByPaymentPartyId(int userId){
        try {
            
            //System.out.println(billMapper.selecPaymentStatusEnumById("2024518151350166"));
            //log.info("bill: {}",billMapper.selectBillById("2024518154338786"));
            List<Bill> bills = billMapper.selectBillsByPaymentPartyId(userId);
            //log.info("bills: {}", billMapper.selectBillsByPaymentPartyId(userId));
            return bills;
            //return Collections.emptyList(); 
        } catch (Exception e) {
            log.error("Error retrieving bills for user ID {}: {}", userId, e.getMessage(), e);
            // Depending on your application's needs, you might want to:
            // - Return an empty list
            // - Re-throw the exception
            // - Return a specific error message/object
             // Example: return an empty list if an exception occurs
            return Collections.emptyList(); 
        }
    }

    public  List<Bill> selectBillsByInitiatorId(int doctorId){
        try {
            List<Bill> bills = billMapper.selectBillsByInitiatorId(doctorId);
            return bills;
        } catch (Exception e) {
            log.error("Error retrieving bills for user ID {}: {}", doctorId, e.getMessage(), e);
            return Collections.emptyList(); 
        }
    }
    

    @Override
    public String createPayment(PaymentRequestDTO paymentRequest) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(
            AlipayConfig.gatewayUrl,
            AlipayConfig.app_id,
            AlipayConfig.merchant_private_key,
            "json",
            AlipayConfig.charset,
            AlipayConfig.alipay_public_key,
            AlipayConfig.sign_type);

        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        System.out.println(paymentRequest.getWIDsubject());
        System.out.println(new String(paymentRequest.getWIDsubject().getBytes("ISO-8859-1"), "utf-8"));
        

        String content = String.format(
            "{\"out_trade_no\":\"%s\",\"total_amount\":\"%s\",\"subject\":\"%s\",\"body\":\"%s\",\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}",
            paymentRequest.getWIDout_trade_no(),
            paymentRequest.getWIDtotal_amount(),
            paymentRequest.getWIDsubject(),
            paymentRequest.getWIDbody()
        );
        System.out.println(content);

        alipayRequest.setBizContent(content);

        //构建支付宝官方支付页面
        String top = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n" +
                "<html>\n" +
                "<head>\n" +
                "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" +
                "<title>付款</title>\n" +
                "</head>";
        System.out.println(top);
        String result = alipayClient.pageExecute(alipayRequest).getBody();
        String bottom = "<body>\n" +
                "</body>\n" +
                "</html>";
        System.out.println(bottom);

        return top + result + bottom;
    }

    public String processNotification(HttpServletRequest request) {
        Map<String, String> params = extractParams(request);
        try {
            if (AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type)) {
                System.out.println("异步验证成功");
                return processVerifiedRequest(request);
            } else {
                System.out.println("异步验证失败");
                return "fail";
            }
        } catch (Exception e) {
            System.out.println("异常：" + e.getMessage());
            return "fail";
        }
    }

    public Map<String, String> extractParams(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        request.getParameterMap().forEach((key, values) -> {
            String valueStr = Arrays.stream(values).collect(Collectors.joining(","));
            try {
                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            params.put(key, valueStr);
        });
        return params;
    }

    public String processVerifiedRequest(HttpServletRequest request) throws UnsupportedEncodingException {
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

        if ("TRADE_FINISHED".equals(trade_status) || "TRADE_SUCCESS".equals(trade_status)) {
            // Logic to handle a successful payment notification
            // e.g., update database records, send confirmation emails, etc.
            System.out.println("订单处理: " + trade_status);
            return "success";
        } else {
            return "fail";
        }
    }

    @Override
    public void updateBill(BillDTO billDto) {
        try {
            billMapper.updateBill(new Bill(billDto));

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
